package com.example.check.realm;

import com.example.check.entity.RoleEntity;
import com.example.check.entity.UserEntity;
import com.example.check.service.RoleService;
import com.example.check.service.UserService;
import com.example.common.GetPassWord;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by Tony Yao on 2017/7/24.
 */
public class MyRealm extends AuthorizingRealm {

    private final Log log = LogFactory.getLog(getClass());

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("dogetAuthorizationInfo被调用了");
        String userAccount = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        try {
            //角色id
            ArrayList<UserEntity> users = userService.SearchUserByField("account", userAccount);
            UserEntity user = users.get(0);
            Set<String> roleSet = new HashSet<>();
            roleSet.add(user.getRoleLevel());

            //权限id集合
            Set<String> perSet = new HashSet<>();
            RoleEntity roleEntity = roleService.SearchRoleByField("level", user.getRoleLevel()).get(0);
            String[] perArr = roleEntity.getPermission().split(",");
            for(String i : perArr){
                perSet.add(i);
            }

            log.info("用户角色" + roleSet.size() + "\n");
            log.info("用户权限"+ perSet.size() + "\n");

            authorizationInfo.setRoles(roleSet);
            authorizationInfo.setStringPermissions(perSet);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
        String userAccount = (String) token.getPrincipal();
        UserEntity user = null;
        try {
            user = userService.SearchUserByField("account", userAccount).get(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (user != null) {
            String password = user.getPassword(); //加密后的密码
            String salt2 = user.getRandomSalt();
            log.info("数据库里的加密密码" + password + "\n");
            log.info("数据库里的随机数盐"+ salt2 + "\n");
            SimpleAuthenticationInfo  ai = new SimpleAuthenticationInfo(userAccount, password, getName());
            ai.setCredentialsSalt(ByteSource.Util.bytes(userAccount + salt2)); //盐是用户名+随机数

            return ai;
        } else {
            return null;
        }

    }

    private static final String OR_OPERATOR = " or ";
    private static final String AND_OPERATOR = " and ";
    private static final String NOT_OPERATOR = "not ";
    /**
     * 支持or and not 关键词  不支持and or混用
     * @param principals
     * @param permission
     * @return
     */
    public boolean isPermitted(PrincipalCollection principals, String permission) {
        if(permission.contains(OR_OPERATOR)) {
            String[] permissions = permission.split(OR_OPERATOR);
            for(String orPermission : permissions) {
                if(isPermittedWithNotOperator(principals, orPermission)) {
                    return true;
                }
            }
            return false;
        } else if(permission.contains(AND_OPERATOR)) {
            String[] permissions = permission.split(AND_OPERATOR);
            for(String orPermission : permissions) {
                if(!isPermittedWithNotOperator(principals, orPermission)) {
                    return false;
                }
            }
            return true;
        } else {
            return isPermittedWithNotOperator(principals, permission);
        }
    }

    private boolean isPermittedWithNotOperator(PrincipalCollection principals, String permission) {
        if(permission.startsWith(NOT_OPERATOR)) {
            return !super.isPermitted(principals, permission.substring(NOT_OPERATOR.length()));
        } else {
            return super.isPermitted(principals, permission);
        }
    }
}
